package com.monochromebytes.mononet.virtual;

import java.util.LinkedList;

/**
 * A queued inbox that receives IncomingDataPackets.
 * 
 * It stores only the last n packets, where n is is the inboxes size. 
 * 
 * This implementation of an Inbox will accept every received packet and returns
 * them in that order they were received.
 * 
 * The
 * 
 * @author ted
 */
public class QueuedInbox {

    /**
     * The packets that were received.
     */
    private final LinkedList<IncomingDataPacket>   packets;

    /**
     * The maximum number of packets the SimpleInbox can hold. Every further
     * packet will cause the first added packet in this SimpleInbox to get
     * removed.
     */
    private int                                    maximumSize;

    /**
     * Creates a new empty SimpleInbox with a maximum size of 1000.
     */
    public QueuedInbox() {
        this(1000);
    }

    /**
     * Creates a new empty SimpleInbox with the given maximum size.
     * 
     * @param maximumSize
     *            The maximum number of packets the SimpleInbox can hold.
     */
    public QueuedInbox(int maximumSize) {
        this.packets = new LinkedList<IncomingDataPacket>();
        this.maximumSize = maximumSize;
    }

    /**
     * If there is no space left in the inbox to receive the new packet the
     * first added packet will be deleted.
     * 
     * @param packet
     *            The received packet.
     */
    public void receive(IncomingDataPacket packet) {
        synchronized (this.packets) {
            if (this.packets.size() == this.maximumSize) {
                this.packets.removeFirst();
            }
            this.packets.addLast(packet);
        }
    }

    /**
     * Returns the next packet from this SimpleInbox.
     * 
     * The packet will be removed from the SimpleInbox. It's up to its
     * implementation which packet will be returned.
     * 
     * No check for emptyness will be performed.
     * 
     * @return The next packet in this SimpleInbox.
     */
    public IncomingDataPacket getNextPacket() {
        synchronized (this.packets) {
            return this.packets.removeFirst();
        }
    }

    /**
     * Returns the number of packets the SimpleInbox contains.
     * 
     * @return The number of packets the SimpleInbox contains.
     */
    public int size() {
        synchronized (this.packets) {
            return this.packets.size();
        }
    }

    /**
     * Returns the maximum size of packets this SimpleInbox can hold.
     * 
     * Every further packet will cause the first added packet in this
     * SimpleInbox to get removed.
     * 
     * @return The maximum size of packets this SimpleInbox can hold.
     */
    public int maximumSize() {
        return this.maximumSize;
    }

    /**
     * Sets the maximum size of packets this SimpleInbox can hold.
     * 
     * Every further packet will cause the first added packet in this
     * SimpleInbox to get removed.
     * 
     * @param maximumSize
     *            The maximum size of packets this SimpleInbox can hold.
     */
    public void setMaximumSize(int maximumSize) {
        this.maximumSize = maximumSize;

        synchronized (this.packets) {
            while (this.packets.size() > maximumSize) {
                this.packets.removeFirst();
            }
        }
    }

    /**
     * Removes all packets added to this Inbox.
     */
    public void clear() {
        synchronized (this.packets) {
            this.packets.clear();
        }
    }
}
